<?php 
/**
 * discuz!金典的加密函数
 * @param string $string 明文 或 密文
 * @param string $operation DECODE表示解密,其它表示加密
 * @param string $key 密匙
 * @param int $expiry 密文有效期
 */
function authcode($string, $operation = 'ENCODE', $key = '', $expiry = 0) {
    // 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
    $ckey_length = 4;
    
    // 密匙
    $key = md5($key ? $key : 'chr6w&H0HXT'); // AUTH_KEY 项目配置的密钥
    
    // 密匙a会参与加解密
    $keya = md5(substr($key, 0, 16));
    // 密匙b会用来做数据完整性验证
    $keyb = md5(substr($key, 16, 16));
    // 密匙c用于变化生成的密文
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
    // 参与运算的密匙
    $cryptkey = $keya.md5($keya.$keyc);
    $key_length = strlen($cryptkey);
    // 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，解密时会通过这个密匙验证数据完整性
    // 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
    $string_length = strlen($string);
    $result = '';
    $box = range(0, 255);
    $rndkey = array();
    // 产生密匙簿
    for($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }
    // 用固定的算法，打乱密匙簿，增加随机性，好像很复杂，实际上对并不会增加密文的强度
    for($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }
    // 核心加解密部分
    for($a = $j = $i = 0; $i < $string_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;
        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        // 从密匙簿得出密匙进行异或，再转成字符
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    }
    
    if($operation == 'DECODE') {
        // substr($result, 0, 10) == 0 验证数据有效性
        // substr($result, 0, 10) - time() > 0 验证数据有效性
        // substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性
        // 验证数据有效性，请看未加密明文的格式
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
            return substr($result, 26);
        } else {
            return '';
        }
    } else {
        // 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
        // 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
        
        return $keyc.str_replace('=', '', base64_encode($result));
    }
}

/**
 * 实现栏目无限分类
 * @param array $data 需要分类的数据
 * @param number $pid 
 * @return array
 */
function threeData($data,$pid=0,$C_count=0){
    $res = array();
    
    foreach ($data as $v){
        if ($v['pid'] == $pid){
            $v['C_count'] = $C_count+1;
            $res[] = $v;
            
            $res = array_merge($res,threeData($data,$v['cat_id'],$v['C_count']));
        }
    }
    return $res;
}


function getKeyWords($id){
    if (!empty($id)){
        $key_ids = M('article_key')->where('art_id='.$id)->getField('key_id',true);
        if (!empty($key_ids)){
            $keys = M('keys')->where(array('id'=>array('in',$key_ids)))->getField('key_name',true);
            
            return implode(',', $keys);
        }
        
    }
    return '';
    
}

/**
 * 字符串截取，支持中文和其他编码
 * static
 * access public
 * @param string $str 需要转换的字符串
 * @param string $length 截取长度
 * @param string $start 开始位置
 * @param string $charset 编码格式
 * @param string $suffix 截断显示字符
 * return string
 */
function msubstr($str,$length, $start=0, $charset="utf-8", $suffix=true) {
    if(function_exists("mb_substr")){
        $slice = mb_substr($str, $start, $length, $charset);
        $strlen = mb_strlen($str,$charset);
    }elseif(function_exists('iconv_substr')){
        $slice = iconv_substr($str,$start,$length,$charset);
        $strlen = iconv_strlen($str,$charset);
    }else{
        $re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
        $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
        $re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
        $re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
        preg_match_all($re[$charset], $str, $match);
        $slice = join("",array_slice($match[0], $start, $length));
        $strlen = count($match[0]);
    }
    if($suffix && $strlen>$length)$slice.='...';
    return $slice;
}

function getIpInfo($ip){
    $url = 'http://apis.juhe.cn/ip/ip2addr?ip=www.juhe.cn&key=JHf874908e710b1b61b1bebd53b7ed2fda';
    
    $json = file_get_contents($url);
    $data = json_decode($json);
    
    dump($data);die;
}

/**
 * 获取access_token
 * @return unknown|mixed|void|NULL|array|string
 */
function getAccessToken(){
    $access_token = cookie('access_token');
    
    if (empty($access_token)){
        // 获取appID 跟 appsecret
        $appID = C('appID');
        $appsecret = C('appsecret');
        
        // 设置请求地址
        $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appID.'&secret='.$appsecret;
        
        $res = https_request($url);
        
        $info = json_decode($res,true);
        $access_token = $info['access_token'];
        cookie('access_token',$access_token,7000);
    }
    return $access_token;
}

/**
 * 模拟网络请求
 * @param unknown $url  请求地址
 * @param unknown $data  请求参数，为空的时候表示发送get请求
 * @return mixed
 */
function https_request($url,$data = null){
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    if (!empty($data)){
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    }
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($curl);
    curl_close($curl);
    return $output;
}

function tag_list($tag_list){
    
    $tag_list = explode(',', $tag_list);
    
    $tags = M('fans_tags')->where(array('id'=>array('in',$tag_list)))->getField('name',true);
    $res= '';
    foreach ($tags as $v){
        $res .= '<label class="label label-success radius">'.$v.'</label> ';
    }
    return $res;
}

function three($data){
    $res = array();
    foreach ($data as $k => $v){
        if($v['pid'] == 0){
            $res[$k] = $v;
            foreach ($data as $c){
                if($c['pid'] == $v['id']){
                    $res[$k]['sub'][] = $c;
                }
            }
        }
    }
    
    return $res;
}






?>